package com.cmcc.pcap.packet.tcp.http.xdr; /**
 *
 */

import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.http.Header;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.cmcc.packet.entity.XdrEntity;
import com.cmcc.pcap.packet.tcp.TcpPacketDecorator;
import com.cmcc.pcap.packet.tcp.http.HttpDecoder;
import com.cmcc.pcap.packet.tcp.http.HttpTransaction;
import com.cmcc.pcap.packet.util.DateUtil;

/**
 * @Date 2018年3月21日 下午6:48:11
 * @author Amish
 *
 */
public class HttpXdrGenerate {
    private static Logger logger = LogManager.getLogger(HttpXdrGenerate.class);

//    public ArrayList<XdrEntity> XdrEntityList = new ArrayList<XdrEntity>();

    public List<XdrEntity> generate(HttpTransaction httpTransaction,String taskId) {
    	
    	ArrayList<XdrEntity> XdrEntityList = new ArrayList<XdrEntity>();

        /**
         * HTTP 协议解析：Header解析，字段获取和计算，基于文本搜索/基于开源HTTP栈
         */
        // TcpConnection tcpConnection = httpTransaction.tcpConnection;
        XdrEntity XdrEntity = new XdrEntity();

        // 用于标记是否解析过response，一个http事物只有一次请求和一次响应
        Integer isAnlysisRsp = 0;

        Iterator<TcpPacketDecorator> i = httpTransaction.al_splited.iterator();
        while (i.hasNext()) {
            HttpRequest request = null;
            HttpResponse response = null;
            TcpPacketDecorator tpd = (TcpPacketDecorator) i.next();
            try {
            	XdrEntity.setTaskId(Integer.valueOf(taskId));//将taskid事先写入entity
            	XdrEntity.setType("HTTP");
            	
                if (tpd.tcpPacket.getPayload() != null && tpd.tcpPacket.getPayload().getRawData().length > 0) {
                    String src = tpd.ipPacket.getHeader().getSrcAddr().getHostAddress() + ":" + tpd.tcpPacket.getHeader().getSrcPort().valueAsInt();

                    if (src.equalsIgnoreCase(httpTransaction.tcpConnection.clientAddr)) {

                        // request = HttpDecoder.decodeRequest(tpd.getData());
                        request = HttpDecoder.decodeRequest(tpd.tcpPacket.getPayload().getRawData());

                        if (request != null) {// TODO 此处如果在做了HTTP事务划分后，一个HttpTransaction中只会有一个Request and
                            // Response，此处代码应该放到外侧？

                            // 填写protocal_type,所有的事务都是http协议
                            XdrEntity.setProtocolType("1");

                            // 将http首部行映射成map
                            Header[] httpMsgRqt = request.getAllHeaders();
                            Map<String, String> httpRequestHeaderMap = new HashMap<String, String>();
                            for (Header msg : httpMsgRqt) {
                                String[] datalist = msg.toString().split(": ");
                                if (datalist.length == 2) {
                                    httpRequestHeaderMap.put(datalist[0], datalist[1]);
                                }
                            }

                            // 填写http version
                            String httpVersion = request.getRequestLine().getProtocolVersion().toString().split("/")[1];
                            switch (httpVersion) {
                                case "0.9":
                                    XdrEntity.setHttpVersion("1");
                                    break;
                                case "1.0":
                                    XdrEntity.setHttpVersion("2");
                                    break;
                                case "1.1":
                                    XdrEntity.setHttpVersion("3");
                                    break;
                                case "2.0":
                                    XdrEntity.setHttpVersion("4");
                                    break;
                                default:
                                    XdrEntity.setHttpVersion("3");
                                    break;
                            }

                            // 填写http message type
                            String messageType = request.getRequestLine().getMethod();
                            switch (messageType) {
                                case "CONNECT":
                                    XdrEntity.setMessageType("1");
                                    break;
                                case "HEAD":
                                    XdrEntity.setMessageType("2");
                                    break;
                                case "PUT":
                                    XdrEntity.setMessageType("3");
                                    break;
                                case "DELETE":
                                    XdrEntity.setMessageType("4");
                                    break;
                                case "POST":
                                    XdrEntity.setMessageType("5");
                                    break;
                                case "GET":
                                    XdrEntity.setMessageType("6");
                                    break;
                                case "TRACE":
                                    XdrEntity.setMessageType("7");
                                    break;
                                case "OPTIONS":
                                    XdrEntity.setMessageType("8");
                                    break;
                                case "PROPFIND":
                                    XdrEntity.setMessageType("9");
                                    break;
                                default:
                                    XdrEntity.setMessageType("6");
                                    break;
                            }

                            // 填写host和host length，以及uri和uri length
                            if (httpRequestHeaderMap.containsKey("Host")) {
                                // 填写host
                                String host = httpRequestHeaderMap.get("Host").trim();
                                Integer hostLength = host.length();
                                // 填写host和host length
                                if (hostLength < 2000) {
                                    XdrEntity.setHost(host);
                                    XdrEntity.setHostLength(hostLength);
                                } else {
                                    XdrEntity.setHost(host.substring(0, 2000));
                                    XdrEntity.setHostLength(2000);
                                }

                                // 填写uri
                                // String uri = "http://" + host + request.getRequestLine().getUri();
                                String uri = host + request.getRequestLine().getUri();
                                Integer uriLength = uri.length();

                                if (uriLength < 2000) {
                                    XdrEntity.setUri(uri);
                                    XdrEntity.setUriLength(uriLength);
                                } else {
                                    XdrEntity.setUri(uri.substring(0, 2000));
                                    XdrEntity.setUriLength(2000);
                                }

//								//填写uri length
//								Integer uriLength = uri.length();
//								XdrEntity.setUriLength(uriLength);

                            } else {
                                // host没有，它的长度写0
                                XdrEntity.setHostLength(0);
                                // uri没有，它的长度写0
                                XdrEntity.setUriLength(0);

                            }

                            // 填写x online host 和 x online host length
                            if (httpRequestHeaderMap.containsKey("X-Online-Host")) {
                                // 填写x online host
                                String xOnlineHost = httpRequestHeaderMap.get("X-Online-Host");
                                XdrEntity.setxOnlineHost(xOnlineHost);

                                // 填写x online host length
                                if (xOnlineHost == null) {
                                    XdrEntity.setxOnlineHostLength(0);
                                } else {
                                    Integer xOnlineHostLength = xOnlineHost.length();
                                    XdrEntity.setxOnlineHostLength(xOnlineHostLength);
                                }
                            } else {
                                XdrEntity.setxOnlineHostLength(0);
                            }

                            // 填写user agent和它的长度
                            if (httpRequestHeaderMap.containsKey("User-Agent")) {
                                // 填写user agent
                                String userAgent = httpRequestHeaderMap.get("User-Agent");
                                Integer userAgentLength = userAgent.length();
                                if (userAgentLength < 2000) {
                                    XdrEntity.setUserAgent(userAgent);
                                    XdrEntity.setUserAgentLength(userAgentLength);
                                } else {
                                    XdrEntity.setReferUri(userAgent.substring(0, 2000));
                                    XdrEntity.setReferUriLength(userAgentLength);
                                }

//								//填写user agent length
//								if(userAgent == null) {
//									XdrEntity.setUserAgentLength(0);
//								}
//								else {
//									Integer userAgentLength = userAgent.length();
//									XdrEntity.setUserAgentLength(userAgentLength);
//								}
                            } else {
                                XdrEntity.setUserAgentLength(0);
                            }

                            // 填写referer和它的长度
                            if (httpRequestHeaderMap.containsKey("Referer")) {
                                // 填写refer
                                String referUri = httpRequestHeaderMap.get("Referer");
                                Integer referUriLength = referUri.length();

                                if (referUriLength < 2000) {
                                    XdrEntity.setReferUri(referUri);
                                    XdrEntity.setReferUriLength(referUriLength);
                                } else {
                                    XdrEntity.setReferUri(referUri.substring(0, 2000));
                                    XdrEntity.setReferUriLength(referUriLength);
                                }

//								//填写refer length
//								if(referUri == null) {
//									XdrEntity.setReferUriLength(0);
//								}
//								else {
//									Integer referUriLength = referUri.length();
//									XdrEntity.setReferUriLength(referUriLength);
//								}
                            } else {
                                XdrEntity.setReferUriLength(0);
                            }

                            // 填写cookie和它的长度
                            if (httpRequestHeaderMap.containsKey("Cookie")) {
                                // 填写cookie
                                String cookie = httpRequestHeaderMap.get("Cookie");
                                Integer cookieLength = cookie.length();

                                if (cookieLength < 2000) {
                                    XdrEntity.setCookie(cookie);
                                    XdrEntity.setCookieLength(cookieLength);
                                } else {
                                    // 超出2000的长度则截取前2000个字符
                                    XdrEntity.setCookie(cookie.substring(0, 2000));
                                    XdrEntity.setCookieLength(2000);
                                }

//								//填写cookie length
//								if(cookie == null)
//									XdrEntity.setCookieLength(0);
//
//								else {
//									Integer cookieLength = cookie.length();
//									XdrEntity.setCookieLength(cookieLength);
//								}
                            } else {
                                XdrEntity.setCookieLength(0);
                            }

                    		//业务识别
                            XdrEntity.setRequest(request);
//                    		Environment environment = ProtocolSpringContextUtils.getBean("environment");
//                    		String systemName = environment.getProperty("system.name");
//                    		String appDistinguishPath = environment.getProperty("file.path.root");//集团规则库目录
//                    		
//                    		TaskAwarenessService taskAwarenessService = ProtocolSpringContextUtils.getBean("taskAwarenessServiceImpl");
//                    		TaskAwarenessEntity entity = taskAwarenessService.getTaskAwarenessById(Long.parseLong(taskId));
//                    		List<String> httpProtoList = entity.getRuleFileList();
//                    		if("awareness".equalsIgnoreCase(systemName)) {
//                    			AppDistinguish appDistinguish = new AppDistinguish();
//                    			Map<String,Object> pathMap = appDistinguish.getAppDistinguishPaths(appDistinguishPath);
//                    			if(entity.getIsUseGroupRule()==1) {//需要使用集团规则库文件
//                    				List<String> groupProtoList = (List<String>)pathMap.get("httpprotoList");
//                    				if(!Collections.isEmpty(groupProtoList)) {
//                    					httpProtoList.addAll(groupProtoList);
//                    				}
//                    			}
//                    			Map<String,String> map = appDistinguish.httpAppDistinguishPcap4j(request, (String)pathMap.get("protolistPath"),httpProtoList);
//                    			if(map!=null) {
//                    				XdrEntity.setAppTypeCd(map.get("appType"));
//                    				XdrEntity.setAppSubTypeCd(map.get("appType")+""+map.get("appSubType"));
//                    			}
//                    		}
                        }

                    } else {
                        // logger.info(new String(tpd.getData()));//temp for test
                        // response = HttpDecoder.decodeResponse(tpd.getData());
                        if (isAnlysisRsp == 0) {
                            response = HttpDecoder.decodeResponse(tpd.tcpPacket.getPayload().getRawData());
                        }
                        if (response != null) {
                            Header[] httpMsgRsp = response.getAllHeaders();
                            Map<String, String> httpResponseHeaderMap = new HashMap<String, String>();
                            for (Header msg : httpMsgRsp) {
                                String[] datalist = msg.toString().split(": ");
                                if (datalist.length == 2) {
                                    httpResponseHeaderMap.put(datalist[0], datalist[1]);
                                }
                            }

                            // 填写http message status
                            String messageStatus = String.valueOf(response.getStatusLine().getStatusCode());
                            XdrEntity.setMessageStatus(messageStatus);

                            // 填写content type字段
                            if (httpResponseHeaderMap.containsKey("Content-Type")) {
                                String httpContentType = httpResponseHeaderMap.get("Content-Type");
                                XdrEntity.setHttpContentType(httpContentType);
                            }

                            // 填写content length字段
                            if (httpResponseHeaderMap.containsKey("Content-Length")) {
                                if (httpResponseHeaderMap.get("Content-Length") != null) {
                                    Integer contentLength = Integer
                                            .valueOf(httpResponseHeaderMap.get("Content-Length").trim());
                                    XdrEntity.setContentLength(contentLength.longValue());
                                } else {
                                    XdrEntity.setContentLength(Integer.valueOf(0).longValue());
                                }
                            } else {
                                XdrEntity.setContentLength(Integer.valueOf(0).longValue());
                            }

                            // 填写location字段
                            if (httpResponseHeaderMap.containsKey("Location")) {
                                String location = httpResponseHeaderMap.get("Location");
                                Integer locationLength = location.length();

                                if (locationLength < 2000) {
                                    XdrEntity.setLocation(location);
                                    XdrEntity.setLocationLength(locationLength);
                                } else {
                                    XdrEntity.setLocation(location.substring(0, 2000));
                                    XdrEntity.setLocationLength(2000);
                                }

//								//填写location length字段
//								if(location == null) {
//									XdrEntity.setLocationLength(0);
//								}
//								else {
//									Integer locationLength = location.length();
//									XdrEntity.setLocationLength(locationLength);;
//								}
                            } else {
                                XdrEntity.setLocationLength(0);
                            }

                            // response解析完之后，将标记为置1
                            isAnlysisRsp = 1;
                        }
                    }
                }
                saveHttpTransactionToXdrEntityList(httpTransaction, XdrEntity);
            } catch (Exception e) {
                logger.error(e.getCause(), e);
                logger.error("Exception info <quintet>: " + tpd.ipPacket.getHeader().getSrcAddr().getHostAddress() + ":" + tpd.tcpPacket.getHeader().getSrcPort().valueAsInt() + "-"
                        + tpd.ipPacket.getHeader().getDstAddr().getHostAddress() + ":" + tpd.tcpPacket.getHeader().getDstPort().valueAsInt());
                logger.error("Exception info <sequence>: " + tpd.tcpPacket.getHeader().getSequenceNumber());
                if (tpd.isReassemble)
                    logger.error("Exception info <segmentsAl size>: " + tpd.segmentsAl.size());
                try {
                    logger.error("Exception info <data>: " + new String(tpd.tcpPacket.getPayload().getRawData(), "utf-8"));
                } catch (UnsupportedEncodingException e1) {
                    logger.error(e.getCause(), e1);
                }
            }
        }

        // 将每个XdrEntity加入XdrEntityList中，调用SaveHttpTransactionInfo的save方法保存到数据库中
        XdrEntityList.add(XdrEntity);
        
        return XdrEntityList;

        /**
         * Interface ProcedureStartTime ProcedureEndTime ProtocolType AppType AppSubType
         * IPAddressType UserIPv4 UserIPv6 ......
         *
         * UL Data上行流量 DL Data下行流量 UL IP Packet上行IP包数 DL IP Packet下行IP包数 UL Disorder IP
         * Packet上行TCP乱序报文数 DL Disorder IP Packet下行TCP乱序报文数 UL Retrans IP
         * Packet上行TCP重传报文数 DL Retrans IP Packet下行TCP重传报文数 UL_IP_FRAG_PACKETS上行IP包的分片数
         * DL_IP_FRAG_PACKETS下行IP包的分片数 TCP SYN Num：TCP SYN次数 TCP SYN ACK Num：TCP SYN
         * ACK的次数 TCP ACK Num：回复SYN ACK的ACK次数
         *
         *
         */

    }

    public void saveHttpTransactionToXdrEntityList(HttpTransaction httpTransaction, XdrEntity XdrEntity)
            throws ParseException {
    	if(httpTransaction.al_splited==null||httpTransaction.al_splited.size()==0)
			return;
        // 判断httptransaction是否是tcpconnection中拆分出来的第一个http事务。如果是的话，al_splited这个list的第四个数据是request请求；如果不是的话，al_splited这个list中的第一个数据是request请求
        Integer length = httpTransaction.al_splited.size();

        TcpPacketDecorator tpdStart = httpTransaction.al_splited.get(0);
        TcpPacketDecorator tpdEnd = httpTransaction.al_splited.get(length - 1);

        if (tpdStart.tcpPacket.getHeader().getSyn()) {
            // 三次握手只会加入到第一个http transaction中，因此有三次握手的http transaction就是第一个请求
            // 填写first request字段
            XdrEntity.setFirstRequest(1);
        } else {
            // 没有三次握手则不属于第一个请求
            XdrEntity.setFirstRequest(0);
        }

        // 计算procedure_start_time
        long timestamp_procedure_start_time = tpdStart.timestamp.getTime();
        Date procedureStartTime = DateUtil.formatTimestamp(timestamp_procedure_start_time);
        XdrEntity.setProcedureStartTime(procedureStartTime);

        // 计算procedure_end_time
        long timestamp_procedure_end_time = tpdEnd.timestamp.getTime();
        Date procedureEndTime = DateUtil.formatTimestamp(timestamp_procedure_end_time);
        XdrEntity.setProcedureEndTime(procedureEndTime);

        // 填写interface
        Integer interFace = 11;
        XdrEntity.setInterfaceCode(interFace);

//		//填写protocal_type
//		String protocol = tpd.protocol.HTTP.toString();
//		XdrEntity.setProtocolType(protocol);

//		填写业务识别类型
//		if(appInfo != null) {
//			//填写APP_type
//			String appType = appInfo.getNum_type();
//			XdrEntity.setAppType(appType);
//
//			//填写APP_SUB_type
//			String appSubType = appInfo.getNum_subtype();
//			XdrEntity.setAppSubType(appSubType);
//		}

        // 找到连接的connectionKey直接填写源地址和目的地址
        String[] connectionKey = httpTransaction.tcpConnection.connectionKey.split("-");
        String[] usersocket = connectionKey[0].split(":");
        String[] serversocket = connectionKey[1].split(":");

        String userIpv4;
        String userIpv6;
        Integer userPort;
        
        String appServerIpIpv4;
        String appServerIpIpv6;
        Integer appServerPort;
        
        if(usersocket.length>2) {
        	//填写终端用户的ipv6地址和端口
        	String[] useriplist = Arrays.copyOf(usersocket, usersocket.length-1);
        	userIpv6 = String.join(":", useriplist);
        	userPort =  Integer.valueOf(usersocket[8]);
        	
        	XdrEntity.setUserIpv6(userIpv6);
        	XdrEntity.setUserPort(userPort);
            
        	// 填写ip_address_type,ipv4是0,ipv6是1
            XdrEntity.setIpAddressType(1);

        }
        else {
        	//填写终端用户的ipv4地址和端口
        	userIpv4 = usersocket[0];
        	userIpv4 = userIpv4.replace("/", "");
        	userPort = Integer.valueOf(usersocket[1]);
        	
        	XdrEntity.setUserIpv4(userIpv4);
        	XdrEntity.setUserPort(userPort);
            
        	// 填写ip_address_type,ipv4是0,ipv6是1
            XdrEntity.setIpAddressType(0);

        }


        // 填写L4 Protocol,0为tcp,1为udp
        XdrEntity.setL4Protocal(0);

        if(serversocket.length>2) {
        	//填写服务端用户的ipv6地址和端口
        	String[] appserveriplist = Arrays.copyOf(serversocket, serversocket.length-1);
        	appServerIpIpv6 = String.join(":", appserveriplist);
        	appServerPort =  Integer.valueOf(serversocket[8]);
        	
        	XdrEntity.setAppServerIpIpv6(appServerIpIpv6);
        	XdrEntity.setAppServerPort(appServerPort);
        }
        else {
        	//填写服务端用户的ipv4地址和端口
        	appServerIpIpv4 = serversocket[0];
        	appServerIpIpv4 = appServerIpIpv4.replace("/", "");
        	appServerPort = Integer.valueOf(serversocket[1]);
        	
        	XdrEntity.setAppServerIpIpv4(appServerIpIpv4);
        	XdrEntity.setAppServerPort(appServerPort);
        }

        // 填写上行流量DL DATA
        Integer ulData = httpTransaction.UL_Data;
        XdrEntity.setUlData(ulData);

        // 填写下行流量UL DATA
        Integer dlData = httpTransaction.DL_Data;
        XdrEntity.setDlData(dlData);

        // 填写上行ip包个数
        Integer ulIpPacket = httpTransaction.UL_IP_Packet;
        XdrEntity.setUlIpPacket(ulIpPacket);

        // 填写下行ip包葛素
        Integer dlIpPacket = httpTransaction.DL_IP_Packet;
        XdrEntity.setDlIpPacket(dlIpPacket);

        // 填写上行tcp乱序包
        Integer ulDisorderIpPacket = httpTransaction.UL_Disorder_IP_Packet;
        XdrEntity.setUlDisorderIpPacket(ulDisorderIpPacket);

        // 填写下行tcp乱序包
        Integer dlDisorderIpPacket = httpTransaction.DL_Disorder_IP_Packet;
        XdrEntity.setDlDisorderIpPacket(dlDisorderIpPacket);

        // 填写上行tcp重传包
        Integer ulRetransIpPacket = httpTransaction.UL_Retrans_IP_Packet;
        XdrEntity.setUlRetransIpPacket(ulRetransIpPacket);

        // 填写下行tcp重传包
        Integer dlRetransIpPacket = httpTransaction.DL_Retrans_IP_Packet;
        XdrEntity.setDlRetransIpPacket(dlRetransIpPacket);

        // 填写上行ip分片数
        Integer ulIpFragPackets = httpTransaction.UL_IP_FRAG_PACKETS;
        XdrEntity.setUlIpFragPackets(ulIpFragPackets);

        // 填写下行ip分片数
        Integer dlIpFragPackets = httpTransaction.DL_IP_FRAG_PACKETS;
        XdrEntity.setDlIpFragPackets(dlIpFragPackets);

        // 填写tcp中syn的次数
        Integer tcpSynNum = httpTransaction.TCP_SYN_Num;
        XdrEntity.setTcpSynNum(tcpSynNum);

        // 填写tcp中syn ack次数
        Integer tcpSynAckNum = httpTransaction.TCP_SYN_ACK_Num;
        XdrEntity.setTcpSynAckNum(tcpSynAckNum);

        // 填写回复syn ack的ack次数
        Integer tcpAckNum = httpTransaction.TCP_ACK_Num;
        XdrEntity.setTcpAckNum(tcpAckNum);

        // 填写IE和PORTAL,默认值是0，必须填写
        XdrEntity.setIe(0);
        XdrEntity.setPortal(0);

    }

}
